package dbsync

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/bmizerany/pq"
	"os"
	"os/exec"
)

//表数据
type Table struct {
	Name string
	Fields []Field
}
type Field struct {
	Name string
	Type string
	Comment string
}

//数据库表 同步到model
type SyncRunIn struct {
	Root string
	//pgsql mysql
	DbType string
	DbHost string
	DbPort string
	DbUser string
	DbPsd string
	DbName string
	TablePrefix string
}
func SyncRun(in *SyncRunIn) {
	var tables []Table
	var err error
	switch in.DbType {
	case "pgsql":
		tables,err = doPgsql(in)
	case "mysql":
		tables,err = doMysql(in)
	default:
		fmt.Println("不支持数据库："+in.DbType)
	}

	if err != nil {
		fmt.Println(err)
		return
	}

	//执行table
	doTables(in.Root,tables)

}

//处理table
func doTables(root string,tables []Table) {
	modelDir := "app/model/"
	err := os.RemoveAll(modelDir)
	fmt.Println("model",err)
	os.Mkdir(modelDir,0666)

	daoDir := "app/dao/"
	err = os.RemoveAll(daoDir)
	fmt.Println("dao",err)
	os.Mkdir(daoDir,0666)

	//创建model
	for _,t := range tables {
		tNameUpper := underToUpper(t.Name)

		//创建model
		content := "package model \n\n"
		content += "type "+tNameUpper+" struct { \n"
		for _,f := range t.Fields {
			content += "//"+f.Comment+"\n"
			content += fmt.Sprintf("%s %s `json:\"%s\"`\n",underToUpper(f.Name),f.Type,f.Name)
		}
		content += "}\n"

		//写入文件
		fileName := modelDir+t.Name+".go"
		file,err := os.OpenFile(fileName,os.O_CREATE|os.O_RDWR,0666)
		if err != nil {
			fmt.Println("模型创建失败",fileName,err)
			continue
		}
		file.WriteString(content)

		cmd := exec.Command("gofmt", "-w", fileName)
		cmd.Run()
		fmt.Println(fileName,"写入完成")
	}

	//创建dao
	for _,t := range tables {
		tNameLower := underToLower(t.Name)
		tNameUpper := underToUpper(t.Name)

		//基础
		content := "package dao \n\n"
		content += "import ( \n"+
			"\""+root+"/app/model\"\n"+
			"\""+root+"/library/db\"\n"+
			"\"gorm.io/gorm\"\n"+
		")\n\n"
		//对象
		content += "type "+tNameUpper+"Dao struct {}\n\n"
		content += "func New"+tNameUpper+"Dao() *"+tNameUpper+"Dao { \n"+
			"return new("+tNameUpper+"Dao)\n"+
		"}\n\n"

		//创建
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao)Create("+tNameLower+" *model."+tNameUpper+") error { \n"+
			"return db.GetMaster().Create("+tNameLower+").Error \n"+
		"}\n\n"

		//删除
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao)Delete(id interface{}) error { \n"+
			"return db.GetMaster().Where(\"id=?\",id).Delete(new(model."+tNameUpper+")).Error \n"+
		"}\n\n"

		//更新
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao)Update(id string, dataMap map[string]interface{}) error { \n"+
			"return db.GetMaster().Model(new(model."+tNameUpper+")).Where(\"id=?\",id).Updates(dataMap).Error\n"+
		"}\n\n"

		//主键查找
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao)Find(id interface{}) (*model."+tNameUpper+",error) { \n"+
			tNameLower+" := new(model."+tNameUpper+")\n"+
			"err := db.GetSlave().Where(\"id=?\",id).Take("+tNameLower+").Error\n"+
			"if err == gorm.ErrRecordNotFound {\n"+
				"err = nil\n"+
			"}\n"+
			"return "+tNameLower+",err\n"+
		"}\n\n"

		//多主键查找
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao)Get(ids []interface{}) ([]model."+tNameUpper+",error) { \n"+
			"var "+tNameLower+"s []model."+tNameUpper+"\n"+
			"err := db.GetSlave().Find(&"+tNameLower+"s,ids).Error\n"+
			"if err == gorm.ErrRecordNotFound {\n"+
				"err = nil\n"+
			"}\n"+
			"return "+tNameLower+"s,err\n"+
		"}\n\n"

		//获取所有
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao) All() ([]model."+tNameUpper+", error) { \n" +
			"var "+tNameLower+"s []model."+tNameUpper+" \n"+
			"err := db.GetSlave().Find(&"+tNameLower+"s).Error \n"+
			"if err == gorm.ErrRecordNotFound { \n"+
				"err = nil \n"+
			"} \n"+
			"return "+tNameLower+"s, err \n"+
		"}\n\n"

		//条件获取单个
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao) FindByWhere(wheres []string, params []interface{}, orders string) (*model."+tNameUpper+", error) { \n" +
			"whereLen := len(wheres) \n" +
			tNameLower+" := new(model."+tNameUpper+") \n"+
			"db := db.GetSlave() \n"+
			"for i:=0;i<whereLen;i++ { \n"+
				"db = db.Where(wheres[i],params[i]) \n"+
			"}\n"+
			"if orders != \"\" { \n"+
				"db = db.Order(orders) \n"+
			"} \n"+
			"err := db.Take(&"+tNameLower+").Error \n"+
			"if err == gorm.ErrRecordNotFound { \n"+
				"err = nil \n"+
			"}\n"+
			"return "+tNameLower+", err \n"+
		"}\n\n"

		//条件获取多个
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao) GetByWhere(wheres []string, params []interface{}, orders string) ([]model."+tNameUpper+", error) { \n" +
			"whereLen := len(wheres) \n" +
			"var "+tNameLower+"s []model."+tNameUpper+" \n"+
			"db := db.GetSlave() \n"+
			"for i:=0;i<whereLen;i++ { \n"+
				"db = db.Where(wheres[i],params[i]) \n"+
			"}\n"+
			"if orders != \"\" { \n"+
				"db = db.Order(orders) \n"+
			"} \n"+
			"err := db.Find(&"+tNameLower+"s).Error \n"+
			"if err == gorm.ErrRecordNotFound { \n"+
			"err = nil \n"+
			"}\n"+
			"return "+tNameLower+"s, err \n"+
		"}\n\n"

		//条件统计
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao) CountByWhere(wheres []string, params []interface{}) (int64, error) { \n"+
			"whereLen := len(wheres) \n"+
			tNameLower+" := new(model."+tNameUpper+") \n"+
			"db := db.GetSlave().Model("+tNameLower+") \n"+
			"for i:=0;i<whereLen;i++ { \n"+
				"db = db.Where(wheres[i],params[i]) \n"+
			"}\n"+
			"var total int64 \n"+
			"err := db.Count(&total).Error \n"+
			"return total, err \n"+
		"}\n\n"

		//分页
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao) ListByWhere(wheres []string, params []interface{}, orders string, offset,limit int) ([]model."+tNameUpper+", error) { \n"+
			"var "+tNameLower+"s []model."+tNameUpper+" \n"+
			"db := db.GetSlave() \n"+
			"for i:=0;i<len(wheres);i++ { \n"+
				"db = db.Where(wheres[i],params[i]) \n"+
			"}\n"+
			"if orders != \"\" { \n"+
				"db = db.Order(orders) \n"+
			"}\n"+
			"err := db.Offset(offset).Limit(limit).Find(&"+tNameLower+"s).Error \n"+
			"if err == gorm.ErrRecordNotFound { \n"+
				"err = nil\n"+
			"}\n"+
			"return "+tNameLower+"s, err"+
		"}\n\n"

		//原生查询
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao) Raw(sql string, params []interface{}, out interface{}) error { \n"+
			"err := db.GetSlave().Raw(sql,params...).Scan(out).Error \n"+
			"if err == gorm.ErrRecordNotFound { \n"+
				"err = nil \n"+
			"}\n"+
			"return err \n"+
		"}\n\n"

		//原生执行
		content += "func ("+tNameLower+"Dao *"+tNameUpper+"Dao) Exec(sql string, params []interface{}) error { \n"+
			"return db.GetSlave().Exec(sql,params).Error \n"+
		"}\n\n"

		fileName := daoDir+t.Name+"_gen.go"
		file,err := os.OpenFile(fileName,os.O_CREATE|os.O_RDWR,0666)
		if err != nil {
			fmt.Println("仓库写入失败",fileName,err)
			return
		}
		file.WriteString(content)

		cmd := exec.Command("gofmt","-w",fileName)
		cmd.Run()
		fmt.Println(fileName,"写入完成")
	}

}



